package com.bx.implatform.ucc.service.Impl;


import com.bx.implatform.entity.User;
import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.service.UserService;
import com.bx.implatform.session.SessionContext;
import com.bx.implatform.session.UserSession;
import com.bx.implatform.ucc.config.UccProperties;
import com.bx.implatform.ucc.dto.CreateRoomParamDTO;
import com.bx.implatform.ucc.dto.CreateRoomParamVO;
import com.bx.implatform.ucc.dto.JrhListParamDTO;
import com.bx.implatform.ucc.entity.UccLoginEntity;
import com.bx.implatform.ucc.entity.UccLoginSysEntity;
import com.bx.implatform.ucc.entity.UccTerminalParamEntity;
import com.bx.implatform.ucc.service.UccApiService;
import com.bx.implatform.ucc.utils.UccExternalApiService;
import com.bx.implatform.util.ConvertNumbers;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class UccApiServiceImpl implements UccApiService {

    @Resource
    private UccExternalApiService externalApiService;
    @Resource
    private UccProperties uccProperties;
    @Resource
    private UserService userService;


    private final ObjectMapper mapper = new ObjectMapper();

    private final RedisTemplate<String, Object> redisTemplate;

    private static final String UCC_TOKEN_KEY = "uccToken:";
    private static final String UCC_SYS_TOKEN_KEY = "uccSysToken:";

    /**
     * 获取token
     *
     * @return
     */
    @Override
    public JsonNode getUccToken() {
        try {
            String url = buildUrl("/system-service/api-v1.0/SysUser/login");
            log.debug("请求融合通讯Token: {}", url);
            long startTime = System.currentTimeMillis();
            // 构建参数
            UserSession session = SessionContext.getSession();
            User user = userService.getById(session.getUserId());
            UccLoginEntity login = new UccLoginEntity(user.getUserName(), user.getPassword(), "zh-cn");
            String response = externalApiService.post(url, login, String.class);
            log.debug("请求门户token接口响应耗时: {}ms, 响应数据: {}",
                    System.currentTimeMillis() - startTime,
                    StringUtils.substring(response, 0, 200));
            JsonNode json = mapper.readTree(response);
            if (!json.has("extraData") || !json.get("extraData").has("token")) {
                throw new GlobalException("获取融合通讯token失败");
            }
            redisTemplate.opsForValue().set(UCC_TOKEN_KEY + session.getUserId(), json.get("extraData").get("token"));
            return ConvertNumbers.convertNumbersToString(json);
        } catch (Exception e) {
            log.error("获取融合通讯token失败: {}", e.getMessage(), e);
            throw new GlobalException("获取融合通讯token失败");
        }
    }

    /**
     * 获取视频通话路数
     *
     * @return
     */
    @Override
    public JsonNode videoCounts() {
        try {
            String url = buildUrl("/video-service/api-v2.0/monitor/counts");
            log.debug("准备调用融合通讯视频通话路数，URL: {}", url);
            JsonNode response = externalApiService.get(url, JsonNode.class);
            return ConvertNumbers.convertNumbersToString(response);
        } catch (Exception e) {
            log.error("调用视频路数接口失败: {}", e.getMessage(), e);
            throw new GlobalException("获取视频路数失败: " + e.getMessage());
        }
    }

    /**
     * 创建固定会议室
     *
     * @return
     */
    @Override
    public JsonNode createRoom(CreateRoomParamVO vo) {
        try {
            String url = buildUrl("/control/api_v2.2.5/conference/add.json");
            log.debug("融合通讯创建固定会议室: {}", url);
            // 构建参数
            CreateRoomParamDTO dto = new CreateRoomParamDTO();
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            dto.setName(uuid);
            dto.setRouteId(null);
            dto.setAccessNum(uuid);
            dto.setAccessNumPw(null);
            dto.setSupportRecord(vo.getSupportRecord());
            dto.setSupportHost(vo.getSupportHost());
            dto.setDeptId(-2);// 全部分区
            dto.setIsVideo(vo.getIsVideo());
            // 构建members
            List<CreateRoomParamDTO.Members> members = new ArrayList<>();
            // 视频，使用调度员
            if(vo.getIsVideo() == 1){
                vo.getUserIds().forEach(m -> {
                    CreateRoomParamDTO.Members member = new CreateRoomParamDTO.Members();
                    JsonNode jsonNode = this.getUserList(null,m, null, null,null, null, "1", "10", null, null);
                    if (jsonNode.get("code") != null && jsonNode.get("code").asInt() == 200) {
                        if (jsonNode.get("data") != null && !jsonNode.get("data").get("list").isEmpty()) {
                            String id = jsonNode.get("data").get("list").get(0).get("id").asText();
                            member.setMemNum(m);// 成员号码
                            member.setTimestamp(String.valueOf(System.currentTimeMillis()));// 时间戳
                            member.setAddressBookId(Integer.parseInt(id));// 成员ID
                            member.setType(6);// 成员类型：1系统分机，2通讯录号码 6调度员
                            members.add(member);
                        } else {
                            throw new GlobalException("创建会议室失败:获取成员调度员信息失败");
                        }
                    }
                });
            } else {
                // 音频，使用系统分机
                UccTerminalParamEntity param = new UccTerminalParamEntity();
                vo.getUserIds().forEach(m -> {
                    CreateRoomParamDTO.Members member = new CreateRoomParamDTO.Members();
                    param.setEmployeeName(m);
                    JsonNode jsonNode = this.queryAll(param);
                    if(jsonNode.get("code") != null && jsonNode.get("code").asInt() == 200){
                        if(jsonNode.get("data") != null && !jsonNode.get("data").get("list").isEmpty()){
                            String exten = jsonNode.get("data").get("list").get(0).get("exten").asText();
                            String extenId = jsonNode.get("data").get("list").get(0).get("id").asText();
                            member.setMemNum(exten);//分机号码
                            member.setTimestamp(String.valueOf(System.currentTimeMillis()));//时间戳
                            member.setEmployeeId(Integer.parseInt(extenId));//分机ID
                            member.setType(1);//成员类型：1系统分机，2通讯录号码
                            members.add(member);
                        } else {
                            throw new GlobalException("创建会议室失败:获取成员分机信息失败");
                        }
                    }
                });
            }

            dto.setMembers(members);
            // 发送请求
            JsonNode response = externalApiService.post(url, dto, JsonNode.class);
            // 获取会议室ID
            if (response.get("code") != null && response.get("code").asInt() == 200) {
                JsonNode jsonNode = this.listRoom(null, uuid, null, null, null, null, null);
                if (jsonNode.get("code") != null && jsonNode.get("code").asInt() == 200) {
                    if (jsonNode.get("data") != null && !jsonNode.get("data").get("list").isEmpty()) {
                        String roomId = jsonNode.get("data").get("list").get(0).get("id").asText();
                        String roomName = jsonNode.get("data").get("list").get(0).get("name").asText();
                        String roomNum = jsonNode.get("data").get("list").get(0).get("accessNum").asText();
                        ObjectNode mutableResponse = (ObjectNode) response;
                        // 创建新的data对象，包含原始data和roomId
                        ObjectNode newData = JsonNodeFactory.instance.objectNode();
                        newData.put("roomName", roomName);
                        newData.put("roomNum", roomNum);
                        newData.put("roomId", roomId);
                        mutableResponse.set("data", newData);
                    } else {
                        throw new GlobalException("创建会议室失败:获取会议室ID失败");
                    }
                }
            }
            return ConvertNumbers.convertNumbersToString(response);
        } catch (Exception e) {
            log.error("融合通讯创建固定会议室失败: {}", e.getMessage(), e);
            throw new GlobalException("融合通讯创建固定会议室失败");
        }
    }

    /**
     * 删除固定会议室
     *
     * @param roomId
     * @return
     */
    @Override
    public JsonNode deleteRoom(Integer roomId) {
        try {
            String url = buildUrl("/control/api_v2.2.5/conference/delete.json");
            log.debug("融合通讯删除固定会议室: {}", url);
            // 构建参数
            Map<String, Object> param = new HashMap<>();
            param.put("id", roomId);
            JsonNode response = externalApiService.post(url, param, JsonNode.class);
            return ConvertNumbers.convertNumbersToString(response);
        } catch (Exception e) {
            log.error("融合通讯删除固定会议室失败: {}", e.getMessage(), e);
            throw new GlobalException("融合通讯删除固定会议室失败");
        }
    }

    /**
     * 获取会议室列表
     *
     * @param accessNum  接入号
     * @param name       会议室名称
     * @param properties 排序字段，默认值为id
     * @param direction  排序方式，正序ASC倒叙DESC默认为正序
     * @param currPage   当前页码，默认为1
     * @param pageLimit  当前数据条数，默认为10条
     * @param userId     用户ID
     * @return
     */
    @Override
    public JsonNode listRoom(
            String accessNum, String name, String properties, String direction,
            Integer currPage, Integer pageLimit, String userId) {
        try {
            String url = buildUrl("/control/api_v2.2.5/conference/query/all.json?" +
                    "properties=id&direction=" + direction + "currPage=" + currPage + "&pageLimit=" + pageLimit);
            if (StringUtils.isNotBlank(accessNum)) {
                url += "&accessNum=" + accessNum;
            }
            if (StringUtils.isNotBlank(name)) {
                url += "&name=" + name;
            }
            if (StringUtils.isNotBlank(userId)) {
                url += "&userId=" + userId;
            }
            log.debug("准备调用融合通讯会议室列表接口，URL: {}", url);
            JsonNode response = externalApiService.get(url, JsonNode.class);
            return ConvertNumbers.convertNumbersToString(response);
        } catch (Exception e) {
            log.error("调用会议室列表接口失败: {}", e.getMessage(), e);
            throw new GlobalException("获取会议室列表信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取全部/分组联系人
     *
     * @param groupId
     * @return
     */
    @Override
    public JsonNode getAllLinkMans(String groupId) {
        try {
            String url = buildUrl("/system-service/api-v1.0/LinkMan/getAllLinkMans?groupId=" +
                    (StringUtils.isNotBlank(groupId) ? groupId : null));
            log.debug("准备调用融合通讯获取全部/分组联系人，URL: {}", url);
            JsonNode response = externalApiService.get(url, JsonNode.class);
            return ConvertNumbers.convertNumbersToString(response);
        } catch (Exception e) {
            log.error("调用获取全部/分组联系人接口失败: {}", e.getMessage(), e);
            throw new GlobalException("获取全部/分组联系人: " + e.getMessage());
        }
    }

    /**
     * 获取系统内所有的视频设备数据
     *
     * @return
     */
    @Override
    public JsonNode queryAllEmplCamera() {
        try {
            String url = buildUrl("/video-service/api-v1.0/Camera/emplCamera/queryAllEmplCamera");
            log.debug("准备调用融合通讯获取系统内所有的视频设备数据，URL: {}", url);
            JsonNode response = externalApiService.get(url, JsonNode.class);
            return ConvertNumbers.convertNumbersToString(response);
        } catch (Exception e) {
            log.error("获取系统内所有的视频设备数据接口失败: {}", e.getMessage(), e);
            throw new GlobalException("获取系统内所有的视频设备数据: " + e.getMessage());
        }
    }

    /**
     * 获取视频设备的视频流
     *
     * @param ip
     * @param port
     * @param user
     * @param password
     * @param rs
     * @param channel
     * @return
     */
    @Override
    public JsonNode getRTMP(String ip, String port, String user, String password, String rs, String channel) {
        try {
            String url = buildUrl("/video-service/api-v1.0/Camera/getRTMP?" +
                    "ip=" + ip + "&user=" + user + "&password=" + password);
            if (StringUtils.isNotBlank(port)) {
                url += "&port=" + port;
            }
            if (StringUtils.isNotBlank(rs)) {
                url += "&rs=" + rs;
            }
            if (StringUtils.isNotBlank(channel)) {
                url += "&channel=" + channel;
            }
            log.debug("准备调用融合通讯获取视频设备的视频流，URL: {}", url);
            JsonNode response = externalApiService.get(url, JsonNode.class);
            return ConvertNumbers.convertNumbersToString(response);
        } catch (Exception e) {
            log.error("获取视频设备的视频流接口失败: {}", e.getMessage(), e);
            throw new GlobalException("获取视频设备的视频流: " + e.getMessage());
        }
    }

    /**
     * 获取融合通讯系统token
     *
     * @return
     */
    @Override
    public JsonNode sysToken() {
        try {
            String url = buildUrl("/control/20140901/infs/login.json");
            UserSession session = SessionContext.getSession();
            log.debug("请求融合通讯系统Token: {}", url);
            String response = externalApiService.get(url, String.class);
            JsonNode json = mapper.readTree(response);
            if (!json.has("token")) {
                throw new GlobalException(json.get("message").asText());
            }
            redisTemplate.opsForValue().set(UCC_SYS_TOKEN_KEY + session.getUserId(), json.get("token"));
            return ConvertNumbers.convertNumbersToString(json);
        } catch (Exception e) {
            log.error("获取融合通讯系统token失败: {}", e.getMessage(), e);
            throw new GlobalException(e.getMessage());
        }
    }

    /**
     * 获取验证码
     */
    @Override
    public JsonNode validateCode() {
        try {
            UserSession session = SessionContext.getSession();
            String url = buildUrl("/control/validateCode/get.json?userName=" + session.getUserId());
            log.debug("请求融合通讯验证码接口: {}", url);
            String response = externalApiService.get(url, String.class);
            JsonNode json = mapper.readTree(response);
            if (!json.has("data") || json.get("data").isNull()) {
                throw new GlobalException(json.get("message").asText());
            }
            return ConvertNumbers.convertNumbersToString(json);
        } catch (Exception e) {
            log.error("获取融合通讯验证码失败: {}", e.getMessage(), e);
            throw new GlobalException(e.getMessage());
        }
    }

    /**
     * 验证token
     */
    @Override
    public JsonNode validate(@Valid UccLoginSysEntity param) {
        try {
            String url = buildUrl("/control/validateCode/validate.json");
            log.debug("请求融合通讯验证验证码接口: {}", url);
            long startTime = System.currentTimeMillis();
            String response = externalApiService.post(url, param, String.class);
            log.debug("请求门户token接口响应耗时: {}ms, 响应数据: {}",
                    System.currentTimeMillis() - startTime,
                    StringUtils.substring(response, 0, 200));
            JsonNode json = mapper.readTree(response);
            if (json.get("code").intValue() != 200) {
                throw new GlobalException(json.get("msg").asText());
            }
            return ConvertNumbers.convertNumbersToString(json);
        } catch (Exception e) {
            log.error("请求融合通讯验证验证码接口失败: {}", e.getMessage(), e);
            throw new GlobalException(e.getMessage());
        }
    }

    /**
     * 获取终端管理列表
     *
     * @param params
     */
    @Override
    public JsonNode queryAll(UccTerminalParamEntity params) {
        try {
            String url = buildUrl("/control/api_v2.2.5/employee/query/queryAll.json");
            log.debug("融合通讯终端管理: {}", url);
            long startTime = System.currentTimeMillis();
            String response = externalApiService.post(url, params, String.class);
            log.debug("融合通讯终端管理接口响应耗时: {}ms, 响应数据: {}",
                    System.currentTimeMillis() - startTime,
                    StringUtils.substring(response, 0, 200));
            JsonNode json = mapper.readTree(response);
            if (json.get("code").intValue() != 200) {
                throw new GlobalException("获取融合通讯终端管理失败" + json.get("msg").asText());
            }
            return ConvertNumbers.convertNumbersToString(json);
        } catch (Exception e) {
            log.error("融合通讯终端管理失败: {}", e.getMessage(), e);
            throw new GlobalException("融合通讯终端管理失败" + e.getMessage());
        }
    }

    /**
     * 获取接入号列表
     *
     * @param dto
     */
    @Override
    public JsonNode jrhList(JrhListParamDTO dto) {
        try {
            String url = buildUrl("/control/20180628/infs/getAccessnumList.json");
            log.debug("获取接入号列表: {}", url);
            // 构建参数
            JsonNode response = externalApiService.post(url, dto, JsonNode.class);
            return ConvertNumbers.convertNumbersToString(response);
        } catch (Exception e) {
            log.error("融合通讯获取接入号列表失败: {}", e.getMessage(), e);
            throw new GlobalException("融合通讯获取接入号列表失败");
        }
    }

    /**
     * 获取调度员列表
     *
     * @param id
     * @param userId
     * @param userName
     * @param deptName
     * @param isAdmin
     * @param exten
     * @param currPage
     * @param pageLimit
     * @param properties
     * @param direction
     */
    @Override
    public JsonNode getUserList(
            String id, String userId, String userName, String deptName, String isAdmin,
            String exten, String currPage, String pageLimit, String properties, String direction) {
        try {
            // 参数校验
            if (StringUtils.isBlank(currPage) || StringUtils.isBlank(pageLimit)) {
                throw new GlobalException("currPage和pageLimit参数不能为空");
            }

            // 使用StringBuilder构建URL
            StringBuilder urlBuilder = new StringBuilder();
            urlBuilder.append(buildUrl("/control/api-v2.3.0/user/query.json?"))
                    .append("currPage=").append(currPage)
                    .append("&pageLimit=").append(pageLimit);

            // 添加可选参数
            appendQueryParam(urlBuilder, "id", id);
            appendQueryParam(urlBuilder, "userId", userId);
            appendQueryParam(urlBuilder, "userName", userName);
            appendQueryParam(urlBuilder, "deptName", deptName);
            appendQueryParam(urlBuilder, "isAdmin", isAdmin);
            appendQueryParam(urlBuilder, "exten", exten);
            appendQueryParam(urlBuilder, "properties", properties);
            appendQueryParam(urlBuilder, "direction", direction);

            String url = urlBuilder.toString();
            log.debug("准备调用融合通讯调度员列表接口，URL: {}", url);

            // 记录请求耗时
            long startTime = System.currentTimeMillis();
            JsonNode response = externalApiService.get(url, JsonNode.class);
            log.debug("调用调度员列表接口耗时: {}ms", System.currentTimeMillis() - startTime);

            return ConvertNumbers.convertNumbersToString(response);
        } catch (Exception e) {
            log.error("调用调度员列表接口失败: {}", e.getMessage(), e);
            throw new GlobalException("获取调度员列表信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取通话记录列表
     *
     * @param caller 主叫号
     * @param callee 被叫号
     * @param startTime 开始时间（不填写时间条件默认查当天的）
     * @param endTime 结束时间
     */
    @Override
    public JsonNode getAllCdrs(String caller, String callee, String startTime, String endTime) {
        try {
            // 使用StringBuilder构建URL
            StringBuilder urlBuilder = new StringBuilder();
            urlBuilder.append(buildUrl("/control/20210628/infs/getAllCdrs.json?"))
                    .append("caller=").append(caller);
            // 添加可选参数
            appendQueryParam(urlBuilder, "callee", callee);
            appendQueryParam(urlBuilder, "startTime", startTime);
            appendQueryParam(urlBuilder, "endTime", endTime);

            String url = urlBuilder.toString();
            log.debug("准备调用融合通讯获取所有话单列表接口，URL: {}", url);

            // 记录请求耗时
            long sTime = System.currentTimeMillis();
            JsonNode response = externalApiService.get(url, JsonNode.class);
            log.debug("调用调融合通讯获取所有话单列表接口耗时: {}ms", System.currentTimeMillis() - sTime);

            return ConvertNumbers.convertNumbersToString(response);
        } catch (Exception e) {
            log.error("调用融合通讯获取所有话单列表接口失败: {}", e.getMessage(), e);
            throw new GlobalException("获取融合通讯获取所有话单列表接口失败: " + e.getMessage());
        }
    }

    /**
     * 下载通话记录文件
     *
     * @param callUuid
     */
    @Override
    public byte[] downCdrFile(String callUuid) {
        try {
            // 使用StringBuilder构建URL
            StringBuilder urlBuilder = new StringBuilder();
            urlBuilder.append(buildUrl("/control/20210615/infs/downCdrFile.json?"))
                    .append("callUuid=").append(callUuid);
            String url = urlBuilder.toString();
            log.debug("准备调用融合通讯下载通话记录文件接口，URL: {}", url);

            // 记录请求耗时
            long sTime = System.currentTimeMillis();
            byte[] bytes = externalApiService.get(url, byte[].class);
            log.debug("调用调融合通讯下载通话记录文件接口耗时: {}ms", System.currentTimeMillis() - sTime);

            return bytes;
            // return ConvertNumbers.convertNumbersToString(response);
        } catch (Exception e) {
            log.error("调用融合通讯下载通话记录文件接口失败: {}", e.getMessage(), e);
            throw new GlobalException("获取融合通讯下载通话记录文件接口失败: " + e.getMessage());
        }
    }

    /**
     * 获取会议成员列表
     *
     * @param confId
     * @param confName
     */
    @Override
    public JsonNode members(Integer confId, String confName) {
        try {
            // 使用StringBuilder构建URL
            StringBuilder urlBuilder = new StringBuilder();
            urlBuilder.append(buildUrl("/system-service/api-v2.0/conference/members?"))
                    .append("confId=").append(confId)
                    .append("&confName=").append(confName);

            String url = urlBuilder.toString();
            log.debug("准备调用融合通讯查询固定会议室成员接口，URL: {}", url);

            // 记录请求耗时
            long sTime = System.currentTimeMillis();
            JsonNode response = externalApiService.get(url, JsonNode.class);
            log.debug("调用调融合通讯查询固定会议室成员接口耗时: {}ms", System.currentTimeMillis() - sTime);

            return ConvertNumbers.convertNumbersToString(response);
        } catch (Exception e) {
            log.error("调用融合通讯查询固定会议室成员接口失败: {}", e.getMessage(), e);
            throw new GlobalException("获取融合通讯查询固定会议室成员接口失败: " + e.getMessage());
        }
    }

    /**
     * 获取视频会议录像列表
     *
     * @param secretKey
     * @param meetingName
     * @param currPage
     * @param pageLimit
     * @param properties
     * @param direction
     */
    @Override
    public JsonNode meetinglog(String secretKey, String meetingName, Integer currPage,
                               Integer pageLimit, String properties, String direction) {
        try {
            // 使用StringBuilder构建URL
            StringBuilder urlBuilder = new StringBuilder();
            urlBuilder.append(buildUrl("/video-conference-system/vcs/public/meetinglog?"))
                    .append("secretKey=").append(secretKey)
                    .append("&meetingName=").append(meetingName)
                    .append("&currPage=").append(currPage)
                    .append("&pageLimit=").append(pageLimit);
            if(StringUtils.isNotBlank(properties)){
                urlBuilder.append("&properties=").append(properties);
            }
            if(StringUtils.isNotBlank(direction)){
                urlBuilder.append("&direction=").append("desc");
            }

            String url = urlBuilder.toString();
            log.info("准备调用融合通讯查询视频会议录像接口，URL: {}", url);

            // 记录请求耗时
            long sTime = System.currentTimeMillis();
            JsonNode response = externalApiService.get(url, JsonNode.class);
            log.info("调用调融合通讯查询视频会议录像接口耗时: {}ms", System.currentTimeMillis() - sTime);

            return ConvertNumbers.convertNumbersToString(response);
        } catch (Exception e) {
            log.error("调用融合通讯查询视频会议录像接口失败: {}", e.getMessage(), e);
            throw new GlobalException("获取融合通讯查询视频会议录像接口失败: " + e.getMessage());
        }
    }

    /**
     * 添加查询参数到URL
     * @param urlBuilder URL构建器
     * @param paramName 参数名
     * @param paramValue 参数值
     */
    private void appendQueryParam(StringBuilder urlBuilder, String paramName, String paramValue) {
        if (StringUtils.isNotBlank(paramValue)) {
            urlBuilder.append("&").append(paramName).append("=")
                    .append(java.net.URLEncoder.encode(paramValue, StandardCharsets.UTF_8));
        }
    }


    private String buildUrl(String path) {
        return uccProperties.getUrl() + path;
    }
}
